#!/usr/bin/env python
# -*- coding:utf-8 -*-
'''
@File    :   adv_features.py
@Time    :   2024/12/30 23:48:01
@Author  :   xiangyu Chen
@Version :   1.0
@Contact :   yu112yu@sina.com
@License :   (C)Copyright 2017-2018, Liugroup-NLPR-CASIA
@Desc    :   高级特性
'''


import os
from collections.abc import Iterable, Iterator
from copy import deepcopy
from dis import dis


def learn_slice():
    """_summary_
        # 切片（Slice）操作符,左闭右开;正数索引从0开始，倒数从-1开始。
        # 前 10 个数，每两个取一个：>>> L[:10:2]
    """
    L = list(range(10))
    print('L: ', L)
    print('L[0,3]: ', L[0:3])
    print('L[-2:]: ', L[-2:])
    print('L[::2]: ', L[::2])
    # tuple 也可以用切片操作
    tL = tuple(range(1, 10, 2))
    print('tL: ', tL)
    print('tL[0,3]: ', tL[0:3])
    print('tL[-2:]: ', tL[-2:])
    print('tL[::2]: ', tL[::2])
    # 字符串也可以用切片操作
    strL = 'abcdefg'
    print('strL: ', strL)
    print('strL[0,3]: ', strL[0:3])
    print('strL[-2:]: ', strL[-2:])
    print('strL[::2]: ', strL[::2])


def learn_iteration():
    """_summary_
        迭代（Iteration）是指对一组数据（如列表、元组、字符串等）进行逐个访问的操作。
        无下标数据也可迭代，可以被迭代的对象，如列表、元组、字符串等。
        通过 collections.abc 模块的 Iterable 类型判断一个对象是可否迭代对象。

    """
    L = list(range(10))
    print('L: ', L)
    for i in L:
        print(i, end='-->')
    print()
    # 迭代器
    tL = tuple(range(1, 10, 2))
    print('tL: ', tL)
    for i in tL:
        print(i, end='-->')
    print()
    print(isinstance(123, Iterable))
    print(isinstance('abc', Iterable))
    print(isinstance((1, 2, 3), Iterable))
    print(isinstance({1, 2, 3}, Iterable))


def learn_listComprehensions():
    """_summary_
        列表推导式（List Comprehensions）是 Python 内置的功能，用来创建列表。
        列表推导可以快速生成列表，比 for 循环和 map()函数更高效。
        列表推导的格式：
            [expr for iter_var in iterable if cond_expr]
    """
    L = list(range(10))
    print('L: ', L)
    print('L[::2]: ', [i for i in L if i % 2 == 0])
    print('L[::-1]: ', [i for i in L[::-1]])

    print('偶数的平方 [x * x for x in range(1, 11) if x % 2 == 0]: ',
          [x * x for x in range(1, 11) if x % 2 == 0])
    print('多层循环 [m + n for m in \'ABC\' for n in \'XYZ\': ',
          [m + n for m in 'ABC' for n in 'XYZ'])
    print('列出当前目录下的所有文件和目录名 [print(\'    \', d) for d in os.listdir(\'.\')]: ')
    [print('    ', d) for d in os.listdir('.')]

    L1 = ['Hello', 'World', 18, 'Apple', None]
    print([s.lower() for s in L1 if isinstance(s, str)])


def learn_generator():
    """_summary_
        生成器（Generator）是特殊的迭代器，在每次迭代中返回一个值，并在下一次迭代中从上次返回的位置开始。
        与列表推导不同，列表推导在生成器表达式结束后立即返回结果，而生成器函数在生成器表达式被调用时才开始生成。
        生成器是一个返回迭代器的函数，只能用于迭代操作，更简单点理解生成器就是一个迭代器。
        格式：
            (expr for iter_var in iterable if cond_expr)
        函数变生成器，返回变成generator 对象： 
            yield
    """
    L = list(range(10))
    print('L: ', L)
    print(
        '(i for i in L if i % 2 == 0)生成器 即L[::2]，返回的是对象: ', (i for i in L if i % 2 == 0))
    print('一般用for in取值：', end='\n\r    ')
    for i in (i for i in L if i % 2 == 0):
        print(i, end='-->')
    print()

    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            a, b = b, a+b
            n += 1
        return 'done'
    print('for i in fib(10):', end='\n\r    ')
    for i in fib(10):
        print(i, end='-->')
    print()

    print('用next() 取值：', end='\n\r    ')
    g = fib(10)
    while True:
        try:
            x = next(g)
            print(x, end='-->')
        except StopIteration as e:
            print('\r\n   ', '用try except捕获 StopIteration 错误，拿到return的返回值:', e)
            break

    # exercises
    def yang_triangle(max):
        n, l = 1, []
        while n <= max:

            # L = deepcopy(l)#用深复制
            # L.append(1)
            # for i in range(1, len(L)-1):
            #     L[i] = l[i-1]+l[i]

            l.append(1)
            reverse = list(range(1, len(l)-1))
            reverse.sort(reverse=True)  # 从后往前算，结果不会影响下一步的计算，一个List就可以处理了
            for i in reverse:
                l[i] = l[i-1]+l[i]

            n += 1
            yield l
        return 'done'
    for i in yang_triangle(10):
        print(i)


def learn_Iterable():
    """_summary_
        可以直接作用于 for 循环的对象统称为可迭代对象
        Iterable 是一个类，表示一个可以被迭代的对象的集合。
        内置的 Iterable 类有：
            str, bytes, list, tuple, set, dict, range, file, generator,
            built-in functions like map(), filter(), zip(), etc.
        任何实现了 __iter__() 或 __getitem__() 方法的对象都被视为 Iterable。
        注意：
            迭代器是 Iterable 的子类，但不是所有的 Iterable 都能被迭代。
            迭代器是一种特殊的 Iterable，它可以被 next() 函数调用并返回数据，直到没有数据时抛 StopIteration 异常。
    """
    print('isinstance(123, Iterable): ', isinstance(123, Iterable))
    print('isinstance(\'abc\', Iterable): ', isinstance('abc', Iterable))

    def fib(max):  # 生成器 generator
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            a, b = b, a+b
            n += 1
        return 'done'
    print('isinstance(fib(10), Iterable): ', isinstance(fib(10), Iterable))


def learn_Iterator():
    """_summary_
        迭代器是一个可以被 next() 函数调用并返回数据，直到没有数据时抛 StopIteration 异常的对象。
        迭代器有两个基本方法：__iter__() 和 __next__()。
        迭代器和 Iterable 最重要的区别在于：
            Iterable 是一个类，表示一个可以被迭代的对象的集合。
            Iterator 是一个类，表示一个可以被 next() 函数调用并返回数据，直到没有数据时抛 StopIteration 异常的对象。
        迭代器和 Iterable 都可以用 for 循环来迭代，但它们的实现细节不同。
        迭代器是 Iterable 的子类，但不是所有的 Iterable 都能被迭代。
        list、dict、str 虽然是 Iterable，却不是Iterator。
    """
    print('isinstance((i for i in range(10)), Iterator): ',
          isinstance((i for i in range(10)), Iterator))

    def fib(max):  # 生成器 generator
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            a, b = b, a+b
            n += 1
        return 'done'
    print('isinstance(fib(10), Iterator): ', isinstance(fib(10), Iterator))
    # list、dict、str 虽然是 Iterable，却不是Iterator。
    print('isinstance([1, 2, 3], Iterator): ', isinstance([1, 2, 3], Iterator))
    print('isinstance({"name": "John", "age": 30}, Iterator): ',
          isinstance({"name": "John", "age": 30}, Iterator))
    print('isinstance(\'abc\', Iterator): ', isinstance('abc', Iterator))
    # 把 list、dict、str 等 Iterable 变成 Iterator 可以使用 iter()函数。
    print('isinstance(iter([1, 2, 3]), Iterator): ',
          isinstance(iter([1, 2, 3]), Iterator))
    print('isinstance(iter({"name": "John", "age": 30}), Iterator): ',
          isinstance(iter({"name": "John", "age": 30}), Iterator))
    print('isinstance(iter(\'abc\'), Iterator): ',
          isinstance(iter('abc'), Iterator))
    # 只有 for 循环才能使用 next() 函数来获取 Iterator 的下一个值。
    # for x in iter([1, 2, 3]):
    #     print(x)
    # for x in iter({"name": "John", "age": 30}):
    #     print(x)
    # for x in iter('abc'):
    #     print(x)
    # 迭代器不一定是 Iterable，反之亦然。

    # 创建迭代器类。
    class ReverseIterator:
        def __iter__(self):
            self.a = 1
            return self

        def __next__(self):
            x = self.a
            self.a += 1
            return x
    print('isinstance(ReverseIterator(),Iterator): ',
          isinstance(ReverseIterator(), Iterator))




if __name__ == '__main__':
    # learn_slice()
    # learn_iteration()
    # learn_listComprehensions()
    # learn_generator()

    # def generate_triangle(n):
    #     triangle = [[1], [1, 1]]
    #     for i in range(2, n):
    #         row = [1]
    #         for j in range(1, i):
    #             row.append(triangle[i-1][j-1] + triangle[i-1][j])
    #         row.append(1)
    #         triangle.append(row)
    #     return triangle
    # print(generate_triangle(5))
    # print()

    # dis(learn_slice)
    # learn_Iterable()
    learn_Iterator()
    pass
